<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Tetris en JavaScript</title>
  <style>
    :root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: dark light;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  padding: 0;
  display: grid;
  place-content: center;
}

section {
  position: absolute;
  background: black;
  width: 100vw;
  height: 100hw;
  top: 0;
  inset: 0;
  display: grid;
  font-size: 48px;
  place-content: center;
}
  </style>
</head>
<body>
  <div id="app">
    <section>Haz click aquí para jugar</section>
    <canvas></canvas>  
  </div>
  <strong>Puntuación: <span></span></strong>
  <script>
    /* constantes */
    const BLOCK_SIZE = 20
    const BOARD_WIDTH = 14
    const BOARD_HEIGHT = 30

    const EVENT_MOVEMENTS = {
      LEFT: 'ArrowLeft',
      DOWN: 'ArrowDown',
      RIGHT: 'ArrowRight'
    }

    const PIECES = [
      [ // la pieza amarilla
        [1, 1],
        [1, 1]
      ],
      [
        [1, 1, 1, 1]
      ],
      [ // es la pieza lila
        [0, 1, 0],
        [1, 1, 1]
      ],
      [ // la pieza verde
        [1, 1, 0],
        [0, 1, 1]
      ],
      [
        [0, 1, 1],
        [1, 1, 0]
      ],
      [
        [1, 0],
        [1, 0],
        [1, 1]
      ],
      [
        [0, 1],
        [0, 1],
        [1, 1]
      ]
    ]

    /* juego */
    // 1. inicializar el canvas
    const canvas = document.querySelector('canvas')
    const context = canvas.getContext('2d')
    const $score = document.querySelector('span')
    const $section = document.querySelector('section')
    const audio = new window.Audio('https://video.aprendejs.dev/tetris.mp3')

    let score = 0

    canvas.width = BLOCK_SIZE * BOARD_WIDTH
    canvas.height = BLOCK_SIZE * BOARD_HEIGHT

    context.scale(BLOCK_SIZE, BLOCK_SIZE)

    // 3. board
    // const board = createBoard(BOARD_WIDTH, BOARD_HEIGHT)

    const board = [
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,
        0, 0
      ],
      [
        1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1,
        0, 0
      ],
      [
        1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1,
        0, 0
      ]
    ]

    function createBoard (width, height) {
      return Array(height).fill().map(() => Array(width).fill(0))
    }

    // 4. pieza player
    const piece = {
      position: { x: 5, y: 5 },
      shape: [
        [1, 1],
        [1, 1]
      ]
    }

    // 2. game loop
    // function update () {
    //   draw()
    //   window.requestAnimationFrame(update)
    // }

    // 8. auto drop
    let dropCounter = 0
    let lastTime = 0

    function update (time = 0) {
      const deltaTime = time - lastTime
      lastTime = time

      dropCounter += deltaTime

      if (dropCounter > 1000) {
        piece.position.y++
        dropCounter = 0

        if (checkCollision()) {
          piece.position.y--
          solidifyPiece()
          removeRows()
        }
      }

      draw()
      window.requestAnimationFrame(update)
    }

    function draw () {
      // todo el tablero
      context.fillStyle = '#000'
      context.fillRect(0, 0, canvas.width, canvas.height)

      board.forEach((row, y) => {
        row.forEach((value, x) => {
          if (value === 1) {
            context.fillStyle = 'yellow'
            context.fillRect(x, y, 1, 1)
          }
        })
      })

      piece.shape.forEach((row, y) => {
        row.forEach((value, x) => {
          if (value) {
            context.fillStyle = 'red'
            context.fillRect(x + piece.position.x, y + piece.position.y, 1, 1)
          }
        })
      })

      $score.innerText = score
    }

    document.addEventListener('keydown', event => {
      if (event.key === EVENT_MOVEMENTS.LEFT) {
        piece.position.x--
        if (checkCollision()) {
          piece.position.x++
        }
      }

      if (event.key === EVENT_MOVEMENTS.RIGHT) {
        piece.position.x++
        if (checkCollision()) {
          piece.position.x--
        }
      }

      if (event.key === EVENT_MOVEMENTS.DOWN) {
        piece.position.y++
        if (checkCollision()) {
          piece.position.y--
          solidifyPiece()
          removeRows()
        }
      }

      if (event.key === 'ArrowUp') {
        const rotated = []

        // ESTO ES LO MÁS COMPLICADO DE LEJOS
        for (let i = 0; i < piece.shape[0].length; i++) {
          const row = []

          for (let j = piece.shape.length - 1; j >= 0; j--) {
            row.push(piece.shape[j][i])
          }

          rotated.push(row)
        }

        const previousShape = piece.shape
        piece.shape = rotated
        if (checkCollision()) {
          piece.shape = previousShape
        }
      }
    })

    function checkCollision () {
      return piece.shape.find((row, y) => {
        return row.find((value, x) => {
          return (
            value === 1 &&
            board[y + piece.position.y]?.[x + piece.position.x] !== 0
          )
        })
      })
    }

    function solidifyPiece () {
      piece.shape.forEach((row, y) => {
        row.forEach((value, x) => {
          if (value === 1) {
            board[y + piece.position.y][x + piece.position.x] = 1
          }
        })
      })

      resetPiece()
    }

    function resetPiece () {
      // reset position
      piece.position.x = Math.floor(BOARD_WIDTH / 2 - 2)
      piece.position.y = 0
      // get random shape
      piece.shape = PIECES[Math.floor(Math.random() * PIECES.length)]
      // gameover
      if (checkCollision()) {
        window.alert('Game over!! Sorry!')
        board.forEach((row) => row.fill(0))
        score = 0
      }
    }

    function removeRows () {
      const rowsToRemove = []

      board.forEach((row, y) => {
        if (row.every(value => value === 1)) {
          rowsToRemove.push(y)
        }
      })

      rowsToRemove.forEach(y => {
        board.splice(y, 1)
        const newRow = Array(BOARD_WIDTH).fill(0)
        board.unshift(newRow)
        score += 10
      })
    }

    $section.addEventListener('click', () => {
      update()

      $section.remove()
      audio.volume = 0.01
      audio.play()
    })
  </script>
</body>
</html>